]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
Rebase recent documents on top of ShellDocSystem
authorColin Walters <walters@verbum.org>
Sun, 29 Nov 2009 22:43:25 +0000 (17:43 -0500)
committerColin Walters <walters@verbum.org>
Tue, 15 Dec 2009 21:08:12 +0000 (16:08 -0500)
Rather of calling .exists() synchronously for all documents, use
ShellDocSystem's async API to only stat docs we're showing.

Use the doc opening functionality in ShellDocSystem.

Also, more intelligently do redisplay(); don't recreate actors
for recent docs if we already have one for that URI.  We may
need more intelligent caching here; if e.g. just the associated
application changes, we should probably reread the info.

https://bugzilla.gnome.org/show_bug.cgi?id=603522

js/misc/docInfo.js
js/ui/docDisplay.js
js/ui/widget.js

index 8123e281bc14328eb5fceecd24338b87c80f1ff1..e60d7ca61c131630fe76f1a25c5dd18fea9137ef 100644 (file)
@@ -32,50 +32,7 @@ DocInfo.prototype = {
     },
 
     launch : function() {
-        // While using Gio.app_info_launch_default_for_uri() would be
-        // shorter in terms of lines of code, we are not doing so
-        // because that would duplicate the work of retrieving the
-        // mime type.
-        let needsUri = Gio.file_new_for_uri(this.uri).get_path() == null;
-        let appInfo = Gio.app_info_get_default_for_type(this.mimeType, needsUri);
-
-        if (appInfo != null) {
-            appInfo.launch_uris([this.uri], Main.createAppLaunchContext());
-        } else {
-            log("Failed to get default application info for mime type " + this.mimeType +
-                ". Will try to use the last application that registered the document.");
-            let appName = this.recentInfo.last_application();
-            let [success, appExec, count, time] = this.recentInfo.get_application_info(appName);
-            if (success) {
-                log("Will open a document with the following command: " + appExec);
-                // TODO: Change this once better support for creating
-                // GAppInfo is added to GtkRecentInfo, as right now
-                // this relies on the fact that the file uri is
-                // already a part of appExec, so we don't supply any
-                // files to appInfo.launch().
-
-                // The 'command line' passed to
-                // create_from_command_line is allowed to contain
-                // '%<something>' macros that are expanded to file
-                // name / icon name, etc, so we need to escape % as %%
-                appExec = appExec.replace(/%/g, "%%");
-
-                let appInfo = Gio.app_info_create_from_commandline(appExec, null, 0, null);
-
-                // The point of passing an app launch context to
-                // launch() is mostly to get startup notification and
-                // associated benefits like the app appearing on the
-                // right desktop; but it doesn't really work for now
-                // because with the way we create the appInfo we
-                // aren't reading the application's desktop file, and
-                // thus don't find the StartupNotify=true in it. So,
-                // despite passing the app launch context, no startup
-                // notification occurs.
-                appInfo.launch([], Main.createAppLaunchContext());
-            } else {
-                log("Failed to get application info for " + this.uri);
-            }
-        }
+        Shell.DocSystem.get_default().open(this.recentInfo);
     },
 
     exists : function() {
@@ -91,50 +48,51 @@ function getDocManager() {
     return docManagerInstance;
 }
 
+/**
+ * DocManager wraps the DocSystem, primarily to expose DocInfo objects
+ * which conform to the GenericDisplay item API.
+ */
 function DocManager() {
     this._init();
 }
 
 DocManager.prototype = {
     _init: function() {
-        this._recentManager = Gtk.RecentManager.get_default();
-        this._items = {};
-        this._recentManager.connect('changed', Lang.bind(this, function(recentManager) {
-            this._reload();
-            this.emit('changed');
-        }));
+        this._docSystem = Shell.DocSystem.get_default();
+        this._infosByTimestamp = [];
+        this._infosByUri = {};
+        this._docSystem.connect('changed', Lang.bind(this, this._reload));
         this._reload();
     },
 
     _reload: function() {
-        let docs = this._recentManager.get_items();
-        let newItems = {};
+        let docs = this._docSystem.get_all();
+        this._infosByTimestamp = [];
+        this._infosByUri = {};
         for (let i = 0; i < docs.length; i++) {
             let recentInfo = docs[i];
-            if (!recentInfo.exists())
-                continue;
 
             let docInfo = new DocInfo(recentInfo);
-
-            // we use GtkRecentInfo URI as an item Id
-            newItems[docInfo.uri] = docInfo;
-        }
-        let deleted = {};
-        for (var uri in this._items) {
-            if (!(uri in newItems))
-                deleted[uri] = this._items[uri];
+            this._infosByTimestamp.push(docInfo);
+            this._infosByUri[docInfo.uri] = docInfo;
         }
-        /* If we'd cached any thumbnail references that no longer exist,
-           dump them here */
-        let texCache = Shell.TextureCache.get_default();
-        for (var uri in deleted) {
-            texCache.evict_recent_thumbnail(this._items[uri].recentInfo);
-        }
-        this._items = newItems;
+        this.emit('changed');
+    },
+
+    getTimestampOrderedInfos: function() {
+        return this._infosByTimestamp;
+    },
+
+    getInfosByUri: function() {
+        return this._infosByUri;
+    },
+
+    lookupByUri: function(uri) {
+        return this._infosByUri[uri];
     },
 
-    getItems: function() {
-        return this._items;
+    queueExistenceCheck: function(count) {
+        return this._docSystem.queue_existence_check(count);
     }
 }
 
index 2b67f50baf57a637ba11026c35a9a4659c31b631..6afcf4fa967b641c64306eaad97b30ff695dff74 100644 (file)
@@ -152,7 +152,8 @@ DocDisplay.prototype = {
     _refreshCache : function() {
         if (!this._docsStale)
             return true;
-        this._allItems = this._docManager.getItems();
+        this._allItems = {};
+        Lang.copyProperties(this._docManager.getInfosByUri(), this._allItems);
         this._docsStale = false;
         return false;
     },
@@ -275,16 +276,21 @@ DashDocDisplayItem.prototype = {
             Main.overview.hide();
         }));
 
+        this.actor._delegate = this;
+
         this._icon = docInfo.createIcon(DASH_DOCS_ICON_SIZE);
         let iconBox = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
         iconBox.append(this._icon, Big.BoxPackFlags.NONE);
         this.actor.append(iconBox, Big.BoxPackFlags.NONE);
-        let name = new St.Label({ style_class: "dash-recent-docs-item",
+        let name = new St.Label({ style_class: 'dash-recent-docs-item',
                                    text: docInfo.name });
         this.actor.append(name, Big.BoxPackFlags.EXPAND);
 
         let draggable = DND.makeDraggable(this.actor);
-        this.actor._delegate = this;
+    },
+
+    getUri: function() {
+        return this._info.uri;
     },
 
     getDragActorSource: function() {
@@ -316,12 +322,14 @@ DashDocDisplay.prototype = {
         this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
         this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
         this.actor.connect('allocate', Lang.bind(this, this._allocate));
+        this._workId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._redisplay));
+
+        this._actorsByUri = {};
 
         this._docManager = DocInfo.getDocManager();
-        this._docManager.connect('changed', Lang.bind(this, function(mgr) {
-            this._redisplay();
-        }));
-        this._redisplay();
+        this._docManager.connect('changed', Lang.bind(this, this._onDocsChanged));
+        this._pendingDocsChange = true;
+        this._checkDocExistence = false;
     },
 
     _getPreferredWidth: function(actor, forHeight, alloc) {
@@ -355,15 +363,17 @@ DashDocDisplay.prototype = {
 
         let firstColumnChildren = Math.ceil(children.length / 2);
 
+        let natural = 0;
         for (let i = 0; i < firstColumnChildren; i++) {
             let child = children[i];
-            let [minSize, naturalSize] = child.get_preferred_height(forWidth);
-            alloc.natural_size += naturalSize;
+            let [minSize, naturalSize] = child.get_preferred_height(-1);
+            natural += naturalSize;
 
             if (i > 0 && i < children.length - 1) {
-                alloc.natural_size += DEFAULT_SPACING;
+                natural += DEFAULT_SPACING;
             }
         }
+        alloc.natural_size = natural;
     },
 
     _allocate: function(actor, box, flags) {
@@ -418,28 +428,49 @@ DashDocDisplay.prototype = {
             i++;
         }
 
-        // Everything else didn't fit, just hide it.
-        for (; i < children.length; i++) {
-            children[i].hide();
+        if (this._checkDocExistence) {
+            // Now we know how many docs we are displaying, queue a check to see if any of them
+            // have been deleted. If they are deleted, then we'll get a 'changed' signal; since
+            // we'll now be displaying items we weren't previously, we'll check again to see
+            // if they were deleted, and so forth and so on.
+            // TODO: We should change this to ask for as many as we can fit in the given space:
+            // https://bugzilla.gnome.org/show_bug.cgi?id=603522#c23
+            this._docManager.queueExistenceCheck(i);
+            this._checkDocExistence = false;
         }
+
+        let skipPaint = [];
+        for (; i < children.length; i++)
+            this.actor.set_skip_paint(children[i], true);
+    },
+
+    _onDocsChanged: function() {
+        this._checkDocExistence = true;
+        Main.queueDeferredWork(this._workId);
     },
 
     _redisplay: function() {
+        // Should be kept alive by the _actorsByUri
         this.actor.remove_all();
-
-        let docs = this._docManager.getItems();
-        let docUrls = [];
-        for (let url in docs) {
-            docUrls.push(url);
+        let docs = this._docManager.getTimestampOrderedInfos();
+        for (let i = 0; i < docs.length; i++) {
+            let doc = docs[i];
+            let display = this._actorsByUri[doc.uri];
+            if (display) {
+                this.actor.add_actor(display.actor);
+            } else {
+                let display = new DashDocDisplayItem(doc);
+                this.actor.add_actor(display.actor);
+                this._actorsByUri[doc.uri] = display;
+            }
         }
-        docUrls.sort(function (urlA, urlB) { return docs[urlB].timestamp - docs[urlA].timestamp; });
-        let textureCache = Shell.TextureCache.get_default();
-
-        for (let i = 0; i < docUrls.length; i++) {
-            let url = docUrls[i];
-            let docInfo = docs[url];
-            let display = new DashDocDisplayItem(docInfo);
-            this.actor.add_actor(display.actor);
+        // Any unparented actors must have been deleted
+        for (let uri in this._actorsByUri) {
+            let display = this._actorsByUri[uri];
+            if (display.actor.get_parent() == null) {
+                display.actor.destroy();
+                delete this._actorsByUri[uri];
+            }
         }
         this.emit('changed');
     }
index 341833d82cbc9c7633b3ed9016d2c047a7f18ffa..b7e8ca3359ed904c1ce0a8106947e3ae0d98d5b4 100644 (file)
@@ -354,8 +354,7 @@ RecentDocsWidget.prototype = {
         for (i = 0; i < docs.length; i++) {
             let docInfo = new DocInfo.DocInfo (docs[i]);
 
-            if (docInfo.exists())
-                items.push(docInfo);
+            items.push(docInfo);
         }
 
         items.sort(function (a,b) { return b.timestamp - a.timestamp; });